package com.qcc.conc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;

/**
 * @创建人 qianchengcheng
 * @创建时间 2022/1/26
 * @描述
 */
public class HomeWorkConc {

    private static Logger log = LoggerFactory.getLogger(HomeWorkConc.class);

    public static void main(String[] args) {

        long start=System.currentTimeMillis();

        // 1.新建一个新线程实现callable接口
        T1 t1 = new T1();
        int t1Res = 0;
        try {
            t1Res = (int) t1.call();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("子线程执行结果为t1Res为:"+t1Res);

        // 2.使用join方法，需等到子线程执行完毕，才继续往下执行。
        try {
            T2 t2 = new T2();
            t2.start();
            Thread.currentThread().join(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 3. while循环判断子线程状态
        T2 t3 = new T2();
        t3.start();
        while (t3.isAlive() == true){

        }

        // 4.synchronized的等待唤醒机制
        Object lock = new Object();
        Thread t4 = new Thread(()->{
            int t4Res = sum();
            System.out.println(Thread.currentThread().getName()+"线程执行结果为:"+t4Res);
            synchronized (lock){// 获取锁
                // 子线程唤醒
                lock.notify();
            }
        });
        t4.start();
        try {
            synchronized (lock){
                // 主线程等待
                lock.wait();
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        // 5.CountDownLatch计数器
        int threadNum = 1;
        final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
        Thread t5 = new Thread(()->{
            int t5Res = sum();
            System.out.println(Thread.currentThread().getName()+"线程执行结果为:"+t5Res);
            // CountDownLatch的线程数-1
            countDownLatch.countDown();
        });
        t5.start();
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 6.Future接口的get方法阻塞当前线程
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        Thread t6 = new Thread(()->{
            int t6Res = sum();
            System.out.println(Thread.currentThread().getName()+"线程执行结果为:"+t6Res);
        });
        Future future = executorService.submit(t6);
        try {
            future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // 7. CyclicBarrier
        CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
        Thread t7 = new Thread(()->{
            int t7Res = sum();
            System.out.println(Thread.currentThread().getName()+"线程执行结果为:"+t7Res);
            try {
                // 阻塞
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        });
        t7.start();
        try {
            //这边也阻塞,并且当阻塞数量达到指定数目时同时释放
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }

        // 8.BlockingQueue
        BlockingQueue blockingQueue = new ArrayBlockingQueue(1);
        Thread t8 = new Thread(()->{
            int t8Res = sum();
            System.out.println(Thread.currentThread().getName()+"线程执行结果为:"+t8Res);
            try {
                blockingQueue.put("t8");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t8.start();
        try {
            // 主线程在队列中获取数据，take()方法会阻塞队列
            blockingQueue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 9.LockSupport
        Thread mainThread = Thread.currentThread();
        Thread t9 = new Thread(() -> {
            int t9Res = sum();
            System.out.println(Thread.currentThread().getName()+"线程执行结果为:"+t9Res);
            LockSupport.unpark(mainThread);
        });
        t9.start();
        LockSupport.park();

        System.out.println("使用时间："+ (System.currentTimeMillis()-start) + " ms");
        System.out.println("退出"+Thread.currentThread().getName()+"主线程");
    }

    static class T1 implements Callable {
        @Override
        public Object call() throws Exception {
            return sum();
        }
    }

    static class T2 extends Thread{
        @Override
        public void run() {
            System.out.println(T2.currentThread().getName()+"线程执行结果为:"+sum());
        }
    }

    private static int sum() {
        return fibo(20);
    }

    private static int fibo(int a) {
        if ( a < 2)
            return 1;
        return fibo(a-1) + fibo(a-2);
    }
}
